/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package br.ufrj.dcc.pushpeer.initialization;

import br.ufrj.dcc.pushpeer.dht.SimpleDHT;
import br.ufrj.dcc.pushpeer.events.Event;
import br.ufrj.dcc.pushpeer.events.EventType;
import br.ufrj.dcc.pushpeer.protocol.PushPeer;

import peersim.config.Configuration;
import peersim.core.Control;
import peersim.core.Network;
import peersim.core.Node;
import peersim.edsim.EDSimulator;
import peersim.transport.Transport;

/**
 * This {@link Control} initializes the nodes that already exist at the beginning of the simulation.
 */
public class NetworkInitializer implements Control {
	
	/**
	* The protocol to operate on.
	*/
	private static final String PAR_PROT="protocol";
	
	/**
	* The transport protocol to use.
	*/
	private static final String PAR_TRANSPORT="transport";
	
	/**
	 * The number of files being simulated.
	 */
	private static final String NUM_FILES="num_files";
	
	/**
	* Protocol identifier, obtained from config property.
	*/
	private final int pid;
	
	/**
	* Transport identifier, obtained from config property.
	*/
	private final int tid;
	
	/**
	 * Number of files being simulated.
	 */
	private int numFiles;
	
	/**
	 * Used to initialize each node.
	 */
	private NodeInitializer init;
	
	public NetworkInitializer(String prefix) {
		pid = Configuration.getPid(prefix+"."+PAR_PROT);
		tid = Configuration.getPid(prefix+"."+PAR_TRANSPORT);
		numFiles = Configuration.getInt(prefix + "." + NUM_FILES);
		init = new NodeInitializer(prefix);
	}
	
	public boolean execute() {
		
		//DHT initialization.
		SimpleDHT.setProtocol(pid);
		for(int i=0; i<Network.size(); i++)
			SimpleDHT.insertNode(Network.get(i));
		
		//The pre-existent nodes are initialized here.
		for(int i=0; i<Network.size(); i++)
			init.initialize(Network.get(i));
		
		//Messages to be sent during initialization.
		//TODO_L: There might be more messages here.
		
		//CB registration.
		for(int i=0; i< Network.size(); i++){
			Node n = Network.get(i);
			Node cb = ((PushPeer)n.getProtocol(pid)).getCB();
			long latency = ((Transport)n.getProtocol(tid)).getLatency(n, cb);
			
			Object ev;
			ev = new Event(EventType.REGISTER_IN_CB, n, latency);
			EDSimulator.add(latency, ev, cb, pid);
		}
		
		//Kickstarts the file piece requests.
		for(int i=0; i< Network.size(); i++){
			Node n = Network.get(i);
			PushPeer p = (PushPeer)n.getProtocol(pid);
			for(int j=1; j <= numFiles; j++)
				if(p.getFileWantedStatus(j) == PushPeer.WANTED)
					p.nextRequest(n, pid, j);
		}
		
		return true;
	}
	
}
